package com.zunipe.ftpe;

import com.zunipe.ftpe.util.Utils;
import com.zunipe.ftpe.util.ZI18n;
import com.zunipe.ftpe.util.ZLog;

import java.io.IOException;
import java.util.List;
import java.util.Scanner;

public class Main implements SelfRunnable {
    public static final String TAG = "Main";

    private FTPConfig mFtpConfig;
    private FTPScanner mFtpScanner;
    private FTPClientWrapper mFtpClientWrapper;
    private FTPDownloader mFtpDownloader;
    private String mTimePoint;
    private boolean mFlag;
    private boolean mScanNow;

    public Main() {
        try {
            mFtpConfig = FTPConfig.getInstance();
            ZLog.i(TAG, ZI18n.getString("main.info.load_config_successfully"), mFtpConfig.printConfig());
            ZLog.i(TAG, ZI18n.getString("main.info.start_looper"));
            mFtpClientWrapper = new FTPClientWrapper(
                    mFtpConfig.getHostname(),
                    mFtpConfig.getPort(),
                    mFtpConfig.getUsername(),
                    mFtpConfig.getPassword()
            );
            mFtpScanner = new FTPScanner(mFtpClientWrapper, mFtpConfig.getPaths());
            mFtpDownloader = new FTPDownloader(mFtpClientWrapper);
            Looper looper = new Looper(1, this);
            looper.start();

            Scanner scanner = new Scanner(System.in);
            CommandHandler mCommandHandler = new CommandHandler(this);
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine().trim();
                if ("stop".equals(line)) {
                    looper.stop();
                    mFtpDownloader.stop();
                    break;
                }
                mCommandHandler.exec(line);
            }
        } catch (IOException e) {
            ZLog.e(TAG, e.toString());
        }
    }

    @Override
    public void run(Looper looper) {
        List<String> timePoints = mFtpConfig.getTimePoints();
        String newTimePoint = Utils.getCurrentTimePoint();
        if (mTimePoint == null || !Utils.isSameTimePoint(mTimePoint, newTimePoint)) {
            mTimePoint = newTimePoint;
            mFlag = false;
        }
        if (mScanNow) {
            mScanNow = false;
            scanFile();
        } else {
            for (String timePoint : timePoints) {
                if (Utils.isSameTimePoint(mTimePoint, timePoint)) {
                    if (!mFlag) {
                        mFlag = true;
                        ZLog.i(TAG, ZI18n.getString("main.info.trigger_timepoint"), timePoint);
                        scanFile();
                        break;
                    }
                }
            }
        }
        mFtpDownloader.checkQueueAndStartDownload();
    }

    private void scanFile() {
        ZLog.i(TAG, ZI18n.getString("main.info.scan_start"));
        try {
            List<ScannerResult> ftpFiles = mFtpScanner.scanFile();
            String matchingFormat = mFtpConfig.getMatchingFormat();
            for (ScannerResult result : ftpFiles) {
                if (result.getSize() > 0) {
                    String scanningFolderNames = result.getFiles().get(0).getName();
                    String fileName = Utils.handlePlaceholders(matchingFormat, scanningFolderNames);
                    String remotePath = result.getPath() + Constants.FTP_SEPARATOR + scanningFolderNames;

                    if (!mFtpConfig.containsDownloadedFile(fileName)) {
                        mFtpDownloader.downloadFile(remotePath,
                                fileName,
                                (name, time) -> {
                                    try {
                                        mFtpConfig.addDownloadedFile(fileName);
                                        ZLog.i(TAG, ZI18n.getString("main.info.download_completed"), fileName, Utils.formatTime(time));
                                    } catch (IOException e) {
                                        ZLog.e(TAG, ZI18n.getString("main.info.save_config_failed"), e.toString());
                                    }
                                }
                        );
                    } else {
                        ZLog.i(TAG, ZI18n.getString("main.info.file_downloaded"), fileName);
                    }
                }
            }
        } catch (IOException e) {
            ZLog.e(TAG, e.toString());
        }
    }

    public void reload() throws IOException {
        mFtpConfig.readConfig();
        mFtpClientWrapper = new FTPClientWrapper(
                mFtpConfig.getHostname(),
                mFtpConfig.getPort(),
                mFtpConfig.getUsername(),
                mFtpConfig.getPassword()
        );
        mFtpScanner = new FTPScanner(mFtpClientWrapper, mFtpConfig.getPaths());
        mFtpDownloader.setFtpClientWrapper(mFtpClientWrapper);
        ZLog.i(TAG, ZI18n.getString("main.info.config_reload_successfully"), mFtpConfig.printConfig());
    }

    public void scanNow() {
        this.mScanNow = true;
    }

    public static void main(String[] args) {
        new Main();
    }
}
